package com.asa.tongji;

import com.asa.HanShu;
import com.asa.utils.Calculate;

/**
 * 设置基本的密度函数
 * @author Administrator
 *
 */
public class BaseFunction {
	
	/**
	 * 正态分布,概率密度函数
	 * 当期望u=0
	 * 方程o*o=1时
	 * 是标准正态分布
	 * @param x	自变量
	 * @param u	均值
	 * @param o	方差
	 * @return
	 */
	
	
	public static double normaldistribution(double x,double u,double o){
		return Math.exp(-(x-u)*(x-u)/(2*o*o))/(Math.sqrt(2*Math.PI)*o);
	}
	
	
	/**
	 * 卡方分布
	 * @param x 概率密度函数中的字变量
	 * @param n	自由度
	 * @param a	gama函数值，放在这里面计算太耗费性能了
	 * @return
	 * @throws Exception 卡方分布自变量x不能小于等于0
	 */
	
	public static double kafangfengbu(double x,int n,double a) throws Exception{
		if (x<=0||n<1) {
			throw new Exception("卡方分布自变量x必须大于0,且n必须大于0");
		}
		return Math.pow(x, (double)n/2-1)*Math.pow(Math.E, -x/2)/(Math.pow(2, (double)n/2)*a);
	}

	/**
	 * 卡方分布精简计算方法，这个方法比较快，但要求n充分大，鬼知道充分是什么，大于50吧
	 * 介于我没搞清楚怎么求分位点就不完成这个方法了
	 * @param a
	 * @param n
	 * @return
	 */
	@Deprecated
	public static double kafanfengbusimple(double a,int n){
		
		double za = 0;
		return Math.pow((za +Math.sqrt(2*n-1)), 2)/2;
	}
	
	/**
	 * t分布
	 * @param t 概率密度函数中的字变量
	 * @param n	自由度
	 * @param a	对于自由度n+1/2的gama函数值
	 * @param b	对于自由度n/2的gama函数值
	 * @return
	 */

	public static double tfengbu(double t,int n,double a,double b){
	
		return a*Math.pow((1+(double)t*t/n), -(double)(n+1)/2)/(Math.sqrt(Math.PI*(double)n)*b);
	}
	/**
	 * t分布
	 * @param t 概率密度函数中的字变量
	 * @param n	自由度
	 * @param a	对于自由度n+1/2的gama函数值
	 * @param b	对于自由度n/2的gama函数值
	 * @return
	 */

	public static double tfengbu(double t,double n,double a,double b){
	
		return a*Math.pow((1+(double)t*t/n), -(double)(n+1)/2)/(Math.sqrt(Math.PI*(double)n)*b);
	}
	/**
	 * t分布精简法，这个计算会比较快，要求是n比较大
	 * @param t
	 * @return
	 */
	public static double tfengbusimple(double t){
		return Math.pow(Math.E, -t*t/2)/Math.sqrt(2*Math.PI);
	}
	
	

	
	
	
	
	
	
	
	
	
	/**
	 * F分布的概率密度函数
	 * @param n1
	 * @param n2
	 * @param y y要大于0的哟
	 * @param a	gamma((n1+n2)/2)
	 * @param b	gamma((double)n1/2
	 * @param c	gamma((double)n2/2)
	 * @return 
	 */

	public static double ffengbu(int n1,int n2,double x,double a,double b,double c){
		return (a*Math.pow(((double)n1/n2),(double)n1/2)*Math.pow(x,(double)n1/2-1))/(b*c*Math.pow(1+((double)n1*x/n2), (double)(n1+n2)/2));
	}
	
	
	

	/**
	 * 泊松分布
	 * @param k	
	 * @param u	泊松分布里面的那个代表期望的参数，有时可以用样本均值代替
	 * @return	
	 */
	public static double bosongfenbu(int k,double u){
		return Math.pow(u, k)*Math.exp(-u)/(double)Calculate.jiecheng(k);
	}
	
	
	
	
	
	
	
	
	
	/**
	 * 伽玛函数（Gamma函数），也叫欧拉第二积分，是阶乘函数在实数与复数上扩展的一类函数。该函数在分析学、概率论、偏微分方程和组合数学中有重要的应用。与之有密切联系的函数是贝塔函数，也叫第一类欧拉积分。可以用来快速计算同伽马函数形式相类似的积分。
	 */
	
	public static double gamma(final double x){
		if (isInt(x)) {
			return gamma((int)x);
		}
		HanShu hanShu = new HanShu() {
			
			@Override
			public double hanshu(double t, double x) {
				// TODO Auto-generated method stub
				return 0;
			}
			
			@Override
			public double hanshu(double x0) {
				// TODO Auto-generated method stub       Math.pow(x0, (2*x)-1)*
				return Math.pow(x0, x-1.0)*Math.pow(Math.E, -x0);
			}
		};
		return Calculate.hanshujifen2(0, 100, hanShu);
	}
	public static long gamma(final int x){
		long all = 1;
		for (int i = 1; i < x; i++) {
			all = all *i;
		}
		
		return all;
	}
	public static boolean isInt(double b){
		
		String str = "" +b;
		String[] split = str.split("\\.");

		double a = Double.parseDouble(split[1]);
		
		if (split[1].length()>1) {
			return false;
		}
		return a==0;

	}
	

	
	
	
	/****************************下面的函数比较简单了************************************/
	
	/**
	 * 指数分布
	 * @param o	概率大于0小于1
	 * @param x	自变量
	 * @return	因变量
	 */
	
	public static double zhishufengbu(double o,double x){
		return Math.pow(Math.E, -x/o)/o;
	}
	
	/**
	 * 泊松分布
	 * @param x 自变量。这个必须是整数
	 * @param n	泊松分布中的那个长得像入字的参数
	 * @return
	 */
	public static double poisso(int x,int n){
		double k = 1;
		for (int i = 1; i <= x; i++) {
			k = k*i;
		}
		return Math.pow(n, x)*Math.pow(Math.E,-n)/k;
	}
	
	
	public static void main(String[] args) {
		  //System.out.println(poisso(0, 3));
	}
	
	
	
}
